package org.example.xsda.service;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.example.xsda.entity.*;
import org.example.xsda.exception.BusinessException;
import org.example.xsda.mapper.*;
import org.example.xsda.vo.StudentProfileVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.List;

/**
 * PDF生成服务
 * 用于生成学生档案PDF，包含防伪水印
 */
@Slf4j
@Service
public class PdfService {

    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private DeptMapper deptMapper;

    @Autowired
    private ClassesMapper classesMapper;

    @Autowired
    private StudentScoreMapper studentScoreMapper;

    @Autowired
    private StudentRecordMapper studentRecordMapper;

    @Autowired
    private ApprovalMapper approvalMapper;

    @Value("${file.storage.local-path}")
    private String localStoragePath;

    // 中文字体
    private static BaseFont chineseFont;

    static {
        try {
            // 使用iText自带的中文字体
            chineseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成学生档案PDF并下载
     */
    public void generateStudentProfilePdf(HttpServletResponse response) {
        try {
            // 获取学生档案数据
            StudentProfileVO profile = getStudentProfile();

            // 设置响应头
            response.setContentType("application/pdf");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode(profile.getRealName() + "_学生档案_" + 
                    LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")), "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".pdf");

            // 生成PDF
            generatePdf(response.getOutputStream(), profile, false);

            log.info("生成学生档案PDF成功：studentId={}, studentName={}", 
                    profile.getStudentId(), profile.getRealName());
        } catch (Exception e) {
            log.error("生成学生档案PDF失败", e);
            throw new BusinessException("生成PDF失败：" + e.getMessage());
        }
    }

    /**
     * 预览学生档案PDF（在线查看）
     */
    public void previewStudentProfilePdf(HttpServletResponse response) {
        try {
            // 获取学生档案数据
            StudentProfileVO profile = getStudentProfile();

            // 设置响应头为inline，浏览器直接打开
            response.setContentType("application/pdf");
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode(profile.getRealName() + "_学生档案", "UTF-8");
            response.setHeader("Content-disposition", "inline;filename*=utf-8''" + fileName + ".pdf");

            // 生成PDF
            generatePdf(response.getOutputStream(), profile, true);

            log.info("预览学生档案PDF成功：studentId={}, studentName={}", 
                    profile.getStudentId(), profile.getRealName());
        } catch (Exception e) {
            log.error("预览学生档案PDF失败", e);
            throw new BusinessException("预览PDF失败：" + e.getMessage());
        }
    }

    /**
     * 生成PDF文档
     */
    private void generatePdf(OutputStream outputStream, StudentProfileVO profile, boolean isPreview) throws Exception {
        Document document = new Document(PageSize.A4, 50, 50, 50, 50);
        PdfWriter writer = PdfWriter.getInstance(document, outputStream);

        // 添加水印事件
        WatermarkPageEvent watermarkEvent = new WatermarkPageEvent(profile, isPreview);
        writer.setPageEvent(watermarkEvent);

        document.open();

        // 标题字体
        Font titleFont = new Font(chineseFont, 20, Font.BOLD);
        Font headFont = new Font(chineseFont, 14, Font.BOLD);
        Font normalFont = new Font(chineseFont, 11, Font.NORMAL);
        Font smallFont = new Font(chineseFont, 9, Font.NORMAL);

        // ========== 文档标题 ==========
        Paragraph title = new Paragraph("学生个人档案", titleFont);
        title.setAlignment(Element.ALIGN_CENTER);
        title.setSpacingAfter(20);
        document.add(title);

        // ========== 证件照 ==========
        if (profile.getIdPhoto() != null && !profile.getIdPhoto().isEmpty()) {
            try {
                Image idPhoto = loadImage(profile.getIdPhoto());
                if (idPhoto != null) {
                    // 设置证件照大小和位置
                    idPhoto.scaleToFit(120, 160); // 1寸照片比例
                    idPhoto.setAlignment(Element.ALIGN_CENTER);
                    idPhoto.setSpacingBefore(10);
                    idPhoto.setSpacingAfter(15);
                    
                    // 添加边框
                    idPhoto.setBorder(Rectangle.BOX);
                    idPhoto.setBorderWidth(1);
                    idPhoto.setBorderColor(BaseColor.GRAY);
                    
                    document.add(idPhoto);
                    
                    // 添加照片说明
                    Paragraph photoLabel = new Paragraph("证件照", smallFont);
                    photoLabel.setAlignment(Element.ALIGN_CENTER);
                    photoLabel.setSpacingAfter(15);
                    document.add(photoLabel);
                }
            } catch (Exception e) {
                log.warn("加载证件照失败：{}", e.getMessage());
                // 证件照加载失败不影响整体PDF生成，继续执行
            }
        }

        // ========== 基本信息 ==========
        document.add(createSectionTitle("一、基本信息", headFont));
        document.add(createInfoTable(new String[][]{
                {"学号", profile.getStudentNo(), "姓名", profile.getRealName()},
                {"性别", profile.getGenderText(), "年龄", profile.getAge() != null ? profile.getAge() + "岁" : "-"},
                {"出生日期", formatDate(profile.getBirthday()), "联系电话", profile.getPhone() != null ? profile.getPhone() : "-"},
                {"家庭住址", profile.getAddress() != null ? profile.getAddress() : "-", "", ""}
        }, normalFont));

        // ========== 学籍信息 ==========
        document.add(createSectionTitle("二、学籍信息", headFont));
        document.add(createInfoTable(new String[][]{
                {"所属院系", profile.getDeptName(), "所在班级", profile.getClassName()},
                {"班主任", profile.getHeadTeacherName() != null ? profile.getHeadTeacherName() : "-", "入学日期", formatDate(profile.getEnrollDate())},
                {"学籍状态", profile.getStatusText(), "账号状态", profile.getAccountStatus() == 1 ? "正常" : "停用"}
        }, normalFont));

        // ========== 学业统计 ==========
        document.add(createSectionTitle("三、学业统计", headFont));
        document.add(createInfoTable(new String[][]{
                {"已修课程", profile.getCourseCount() + "门", "总学分", String.format("%.1f分", profile.getTotalCredits())},
                {"平均成绩", String.format("%.2f分", profile.getAverageScore()), "档案记录", profile.getRecordCount() + "条"}
        }, normalFont));

        // ========== 成绩记录 ==========
        document.add(createSectionTitle("四、成绩记录（最近10条）", headFont));
        if (profile.getRecentScores() != null && !profile.getRecentScores().isEmpty()) {
            PdfPTable scoreTable = new PdfPTable(4);
            scoreTable.setWidthPercentage(100);
            scoreTable.setSpacingBefore(10);
            scoreTable.setSpacingAfter(15);
            scoreTable.setWidths(new float[]{2, 4, 2, 2});

            // 表头
            addTableHeader(scoreTable, new String[]{"学期", "课程名称", "成绩", "学分"}, normalFont);

            // 数据行
            int count = 0;
            for (StudentProfileVO.RecentScore score : profile.getRecentScores()) {
                if (count >= 10) break;
                addTableCell(scoreTable, score.getSemester(), smallFont);
                addTableCell(scoreTable, score.getCourseName(), smallFont);
                addTableCell(scoreTable, String.valueOf(score.getScore()), smallFont);
                addTableCell(scoreTable, String.valueOf(score.getCredit()), smallFont);
                count++;
            }

            document.add(scoreTable);
        } else {
            Paragraph noData = new Paragraph("暂无成绩记录", normalFont);
            noData.setSpacingBefore(10);
            noData.setSpacingAfter(15);
            document.add(noData);
        }

        // ========== 档案记录 ==========
        document.add(createSectionTitle("五、档案记录（最近10条）", headFont));
        if (profile.getRecentRecords() != null && !profile.getRecentRecords().isEmpty()) {
            PdfPTable recordTable = new PdfPTable(3);
            recordTable.setWidthPercentage(100);
            recordTable.setSpacingBefore(10);
            recordTable.setSpacingAfter(15);
            recordTable.setWidths(new float[]{2, 5, 3});

            // 表头
            addTableHeader(recordTable, new String[]{"记录类型", "内容", "创建时间"}, normalFont);

            // 数据行
            int count = 0;
            for (StudentProfileVO.RecentRecord record : profile.getRecentRecords()) {
                if (count >= 10) break;
                addTableCell(recordTable, record.getRecordType(), smallFont);
                addTableCell(recordTable, record.getContent(), smallFont);
                addTableCell(recordTable, formatDateTime(record.getCreateTime()), smallFont);
                count++;
            }

            document.add(recordTable);
        } else {
            Paragraph noData = new Paragraph("暂无档案记录", normalFont);
            noData.setSpacingBefore(10);
            noData.setSpacingAfter(15);
            document.add(noData);
        }

        // ========== 文档底部 ==========
        document.add(new Paragraph(" ", normalFont)); // 空行
        Paragraph footer = new Paragraph("生成时间：" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss")), smallFont);
        footer.setAlignment(Element.ALIGN_RIGHT);
        document.add(footer);

        Paragraph note = new Paragraph("注：本档案由学生档案管理系统自动生成，仅供参考。", smallFont);
        note.setAlignment(Element.ALIGN_CENTER);
        note.setSpacingBefore(20);
        document.add(note);

        document.close();
    }

    /**
     * 创建章节标题
     */
    private Paragraph createSectionTitle(String text, Font font) {
        Paragraph paragraph = new Paragraph(text, font);
        paragraph.setSpacingBefore(15);
        paragraph.setSpacingAfter(10);
        return paragraph;
    }

    /**
     * 创建信息表格
     */
    private PdfPTable createInfoTable(String[][] data, Font font) throws DocumentException {
        PdfPTable table = new PdfPTable(4);
        table.setWidthPercentage(100);
        table.setSpacingAfter(15);
        table.setWidths(new float[]{2, 3, 2, 3});

        for (String[] row : data) {
            for (int i = 0; i < row.length; i += 2) {
                if (i + 1 < row.length) {
                    // 标签单元格（粗体）
                    PdfPCell labelCell = new PdfPCell(new Phrase(row[i], new Font(chineseFont, 11, Font.BOLD)));
                    labelCell.setBackgroundColor(new BaseColor(240, 240, 240));
                    labelCell.setPadding(8);
                    labelCell.setHorizontalAlignment(Element.ALIGN_CENTER);
                    table.addCell(labelCell);

                    // 值单元格
                    PdfPCell valueCell = new PdfPCell(new Phrase(row[i + 1], font));
                    valueCell.setPadding(8);
                    if (row[i + 1].isEmpty() && i + 2 >= row.length) {
                        valueCell.setColspan(3); // 跨列
                    }
                    table.addCell(valueCell);
                }
            }
        }

        return table;
    }

    /**
     * 添加表头
     */
    private void addTableHeader(PdfPTable table, String[] headers, Font font) {
        for (String header : headers) {
            PdfPCell cell = new PdfPCell(new Phrase(header, new Font(chineseFont, 11, Font.BOLD)));
            cell.setBackgroundColor(new BaseColor(200, 220, 240));
            cell.setPadding(8);
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            table.addCell(cell);
        }
    }

    /**
     * 添加表格单元格
     */
    private void addTableCell(PdfPTable table, String text, Font font) {
        PdfPCell cell = new PdfPCell(new Phrase(text, font));
        cell.setPadding(6);
        table.addCell(cell);
    }

    /**
     * 格式化日期
     */
    private String formatDate(LocalDate date) {
        if (date == null) return "-";
        return date.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
    }

    /**
     * 格式化日期时间
     */
    private String formatDateTime(LocalDateTime dateTime) {
        if (dateTime == null) return "-";
        return dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
    }

    /**
     * 获取当前学生的档案数据
     */
    private StudentProfileVO getStudentProfile() {
        // 1. 获取当前登录用户ID
        Long userId = StpUtil.getLoginIdAsLong();

        // 2. 根据userId查找student记录
        LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Student::getUserId, userId);
        Student student = studentMapper.selectOne(wrapper);

        if (student == null) {
            throw new BusinessException("未找到学生信息，请联系管理员");
        }

        // 3. 构建VO
        StudentProfileVO profile = new StudentProfileVO();

        // ==== 基本信息 ====
        profile.setStudentId(student.getId());
        profile.setStudentNo(student.getStudentNo());
        profile.setGender(student.getGender());
        profile.setGenderText(student.getGender() == 1 ? "男" : "女");
        profile.setBirthday(student.getBirthday());

        // 计算年龄
        if (student.getBirthday() != null) {
            Period age = Period.between(student.getBirthday(), LocalDate.now());
            profile.setAge(age.getYears());
        }

        profile.setPhone(student.getPhone());
        profile.setAddress(student.getAddress());

        // ==== 学籍信息 ====
        profile.setDeptId(student.getDeptId());
        profile.setClassId(student.getClassId());
        profile.setEnrollDate(student.getEnrollDate());

        if (student.getEnrollDate() != null) {
            profile.setEnrollYear(student.getEnrollDate().getYear());
        }

        profile.setStatus(student.getStatus());
        profile.setStatusText(getStatusText(student.getStatus()));
        profile.setRemark(student.getRemark());

        // 院系信息
        if (student.getDeptId() != null) {
            Dept dept = deptMapper.selectById(student.getDeptId());
            if (dept != null) {
                profile.setDeptName(dept.getDeptName());
            }
        }

        // 班级信息
        if (student.getClassId() != null) {
            Classes classes = classesMapper.selectById(student.getClassId());
            if (classes != null) {
                profile.setClassName(classes.getClassName());

                // 班主任信息
                if (classes.getHeadTeacherId() != null) {
                    SysUser headTeacher = sysUserMapper.selectById(classes.getHeadTeacherId());
                    if (headTeacher != null) {
                        profile.setHeadTeacherName(headTeacher.getRealName());
                    }
                }
            }
        }

        // ==== 账号信息 ====
        profile.setUserId(userId);
        SysUser user = sysUserMapper.selectById(userId);
        if (user != null) {
            profile.setRealName(user.getRealName());
            profile.setAvatar(user.getAvatar()); // 头像（来自sys_user）
            profile.setUsername(user.getUsername());
            profile.setAccountStatus(user.getStatus());

            // 角色信息
            if (user.getRoleId() != null) {
                profile.setRoleName("学生");
            }
        }
        
        // 证件照（来自student表）
        profile.setIdPhoto(student.getIdPhoto());

        // ==== 统计信息 ====
        // 总学分和平均分
        LambdaQueryWrapper<StudentScore> scoreWrapper = new LambdaQueryWrapper<>();
        scoreWrapper.eq(StudentScore::getStudentId, student.getId());
        List<StudentScore> scores = studentScoreMapper.selectList(scoreWrapper);

        if (!scores.isEmpty()) {
            double totalCredits = scores.stream()
                    .mapToDouble(s -> s.getCredit() != null ? s.getCredit().doubleValue() : 0.0)
                    .sum();
            double avgScore = scores.stream()
                    .mapToDouble(s -> s.getScore() != null ? s.getScore().doubleValue() : 0.0)
                    .average()
                    .orElse(0.0);

            profile.setTotalCredits(totalCredits);
            profile.setAverageScore(Math.round(avgScore * 100.0) / 100.0);
            profile.setCourseCount(scores.size());
        } else {
            profile.setTotalCredits(0.0);
            profile.setAverageScore(0.0);
            profile.setCourseCount(0);
        }

        // 档案记录数
        LambdaQueryWrapper<StudentRecord> recordWrapper = new LambdaQueryWrapper<>();
        recordWrapper.eq(StudentRecord::getStudentId, student.getId());
        Long recordCount = studentRecordMapper.selectCount(recordWrapper);
        profile.setRecordCount(recordCount.intValue());

        // 待审批申请数
        LambdaQueryWrapper<Approval> approvalWrapper = new LambdaQueryWrapper<>();
        approvalWrapper.eq(Approval::getStudentId, student.getId());
        approvalWrapper.eq(Approval::getStatus, 0);
        Long pendingCount = approvalMapper.selectCount(approvalWrapper);
        profile.setPendingApprovalCount(pendingCount.intValue());

        // ==== 最近成绩（前10条）====
        LambdaQueryWrapper<StudentScore> recentScoreWrapper = new LambdaQueryWrapper<>();
        recentScoreWrapper.eq(StudentScore::getStudentId, student.getId());
        recentScoreWrapper.orderByDesc(StudentScore::getCreateTime);
        recentScoreWrapper.last("LIMIT 10");
        List<StudentScore> recentScores = studentScoreMapper.selectList(recentScoreWrapper);

        java.util.List<StudentProfileVO.RecentScore> recentScoreList = new java.util.ArrayList<>();
        for (StudentScore score : recentScores) {
            StudentProfileVO.RecentScore rs = new StudentProfileVO.RecentScore();
            rs.setCourseName(score.getCourseName());
            rs.setScore(score.getScore() != null ? score.getScore().doubleValue() : 0.0);
            rs.setCredit(score.getCredit() != null ? score.getCredit().doubleValue() : 0.0);
            rs.setSemester(score.getSemester());
            rs.setCreateTime(score.getCreateTime());
            recentScoreList.add(rs);
        }
        profile.setRecentScores(recentScoreList);

        // ==== 最近档案记录（前10条）====
        LambdaQueryWrapper<StudentRecord> recentRecordWrapper = new LambdaQueryWrapper<>();
        recentRecordWrapper.eq(StudentRecord::getStudentId, student.getId());
        recentRecordWrapper.orderByDesc(StudentRecord::getCreateTime);
        recentRecordWrapper.last("LIMIT 10");
        List<StudentRecord> recentRecords = studentRecordMapper.selectList(recentRecordWrapper);

        java.util.List<StudentProfileVO.RecentRecord> recentRecordList = new java.util.ArrayList<>();
        for (StudentRecord record : recentRecords) {
            StudentProfileVO.RecentRecord rr = new StudentProfileVO.RecentRecord();
            rr.setRecordType(getRecordTypeName(record.getRecordType()));
            rr.setContent(record.getContent());
            rr.setCreateTime(record.getCreateTime());
            recentRecordList.add(rr);
        }
        profile.setRecentRecords(recentRecordList);

        return profile;
    }

    private String getStatusText(Integer status) {
        if (status == null) return "未知";
        switch (status) {
            case 1: return "在籍";
            case 2: return "休学";
            case 3: return "毕业";
            case 4: return "退学";
            default: return "未知";
        }
    }

    private String getRecordTypeName(Integer recordType) {
        if (recordType == null) return "未知";
        switch (recordType) {
            case 1: return "奖惩记录";
            case 2: return "异动记录";
            default: return "其他";
        }
    }

    /**
     * 加载图片（支持本地路径和网络URL）
     */
    private Image loadImage(String imageUrl) {
        try {
            if (imageUrl == null || imageUrl.isEmpty()) {
                return null;
            }

            // 如果是网络URL（http或https开头）
            if (imageUrl.startsWith("http://") || imageUrl.startsWith("https://")) {
                return Image.getInstance(new java.net.URL(imageUrl));
            }

            // 如果是本地路径（/files/...）
            if (imageUrl.startsWith("/files/")) {
                // 转换为实际文件路径
                String relativePath = imageUrl.replace("/files/", "");
                String fullPath = localStoragePath + java.io.File.separator + relativePath.replace("/", java.io.File.separator);
                
                java.io.File file = new java.io.File(fullPath);
                if (file.exists()) {
                    return Image.getInstance(fullPath);
                } else {
                    log.warn("图片文件不存在：{}", fullPath);
                    return null;
                }
            }

            // 直接作为文件路径尝试加载
            return Image.getInstance(imageUrl);
        } catch (Exception e) {
            log.error("加载图片失败：{}", imageUrl, e);
            return null;
        }
    }

    /**
     * 水印页面事件
     */
    static class WatermarkPageEvent extends PdfPageEventHelper {
        private StudentProfileVO profile;
        private boolean isPreview;

        public WatermarkPageEvent(StudentProfileVO profile, boolean isPreview) {
            this.profile = profile;
            this.isPreview = isPreview;
        }

        @Override
        public void onEndPage(PdfWriter writer, Document document) {
            PdfContentByte canvas = writer.getDirectContentUnder();

            try {
                // 获取页面尺寸
                Rectangle pageSize = document.getPageSize();
                float pageWidth = pageSize.getWidth();

                // 水印文本
                String watermarkText = profile.getStudentNo() + " " + profile.getRealName();
                String timeText = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));

                // 设置透明度
                PdfGState gState = new PdfGState();
                gState.setFillOpacity(0.1f);
                canvas.setGState(gState);

                // 绘制斜向水印（多行）
                canvas.saveState();
                for (int i = 0; i < 8; i++) {
                    for (int j = 0; j < 5; j++) {
                        canvas.beginText();
                        canvas.setFontAndSize(chineseFont, 40);
                        canvas.setColorFill(BaseColor.GRAY);
                        canvas.showTextAligned(Element.ALIGN_CENTER, 
                                watermarkText, 
                                100 + i * 150, 
                                100 + j * 150, 
                                45);
                        canvas.endText();
                    }
                }
                canvas.restoreState();

                // 底部防伪信息（不透明）
                canvas.saveState();
                PdfGState normalState = new PdfGState();
                normalState.setFillOpacity(0.3f);
                canvas.setGState(normalState);

                canvas.beginText();
                canvas.setFontAndSize(chineseFont, 8);
                canvas.setColorFill(BaseColor.GRAY);
                canvas.showTextAligned(Element.ALIGN_CENTER, 
                        "防伪码：XSDA-" + profile.getStudentNo() + "-" + System.currentTimeMillis(), 
                        pageWidth / 2, 
                        20, 
                        0);
                canvas.endText();

                canvas.beginText();
                canvas.setFontAndSize(chineseFont, 8);
                canvas.showTextAligned(Element.ALIGN_CENTER, 
                        "生成时间：" + timeText + (isPreview ? " (预览)" : ""), 
                        pageWidth / 2, 
                        10, 
                        0);
                canvas.endText();

                canvas.restoreState();

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

